import {
  SplitScreen1,
  SplitScreen2,
  SplitScreen3,
  SplitScreen4,
  SplitScreen5,
} from '@/components/Icons';
import LivePlayer from '@/components/LivePlayer';
import { home, move, stop, zoom } from '@/services/PTZService';
import { getActive, setActive } from '@/services/PreviewService';
import { saveScreenshot } from '@/services/SourceSerivce';
import {
  InputSourceConfig,
  OutputSourceConfig,
  PTZControlType,
  RecordDataType,
} from '@/types';
import { useModel } from '@umijs/max';
import { Menu, message } from 'antd';
import { useEffect, useRef, useState } from 'react';
import { useDrag, useDrop } from 'react-dnd';
import SVG from 'react-inlinesvg';
import { isNotBlank } from 'web-plugin-utils';
import styles from './style.less';

import { setRecordPath } from '@/services/OsSerivce';
import { addVideo } from '@/services/RecordService';
import { v4 as uuidV4 } from 'uuid';
/**
 * 拖拽项
 * @param config
 * @param onChangeFuse
 * @param onChangePutInWorkerName
 */
const DragItem = ({
  config,
  onChangeFuse,
  onChangePutInWorkerName,
}: {
  config: InputSourceConfig;
  onChangeFuse: (fuse: boolean) => void;
  onChangePutInWorkerName: (putInWorkerName?: string) => void;
}) => {
  const [{ isDragging }, drag] = useDrag(() => ({
    type: 'item',
    item: { ...config },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
      handlerId: monitor.getHandlerId(),
    }),
  }));

  const opacity = isDragging ? 0.4 : 1;

  useEffect(() => {
    if (isDragging) {
      onChangeFuse(true);
      onChangePutInWorkerName(config.workerName);
    } else {
      onChangeFuse(false);
    }
  }, [isDragging]);

  return (
    <div ref={drag} style={{ width: '100%', height: '100%', opacity }}>
      {config.label}
    </div>
  );
};

/**
 * 拖拽容器
 */
export const DropContainer = ({
  onDrop,
}: {
  onDrop: (config: InputSourceConfig) => void;
}) => {
  const [{ canDrop, isOver }, drop] = useDrop(() => ({
    accept: 'item',
    drop: (item: InputSourceConfig) => {
      onDrop(item);
      return item;
    },
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    }),
  }));

  const isActive = canDrop && isOver;
  let color = '#000';
  if (isActive) {
    color = 'darkgreen';
  } else if (canDrop) {
    color = '#000';
  }

  return (
    <div
      className={styles.dropTitleWrap}
      ref={drop}
      style={{ color }}
      data-testid="dustbin"
    >
      <p className={styles.dropTitle}>
        {isActive ? '松开放入' : '拖拽到此处放入'}
      </p>
    </div>
  );
};

const LeftInput = ({
  putInWorkerName,
  workerName,
  onMenuClick,
  onChangeFuse,
  onChangePutInWorkerName,
}: {
  putInWorkerName?: string;
  workerName?: string;
  onMenuClick: (workerName: string) => void;
  onChangeFuse: (fuse: boolean) => void;
  onChangePutInWorkerName: (putInWorkerName?: string) => void;
}) => {
  const { enabledInputSourceConfigs, reloadInputSourceConfigs } =
    useModel('inputSource');

  useEffect(() => {
    reloadInputSourceConfigs();
  }, []);

  return (
    <div className={styles.leftInput}>
      <div className={styles.title}>输入源</div>
      <Menu
        selectedKeys={
          isNotBlank(putInWorkerName!)
            ? [putInWorkerName!]
            : isNotBlank(workerName!)
            ? [workerName!]
            : undefined
        }
        onClick={(info) => {
          onMenuClick(info.key);
        }}
        style={{ width: 256 }}
        mode="inline"
        items={[
          ...enabledInputSourceConfigs.map((v: InputSourceConfig) => ({
            key: v.workerName,
            label: (
              <div
                style={{ width: '100%', height: '100%' }}
                draggable={workerName?.includes('output')}
                onDragStart={() => {
                  onChangeFuse(true);
                  onChangePutInWorkerName(v.workerName);
                }}
                onDragEnd={() => {
                  onChangeFuse(false);
                }}
              >
                <DragItem
                  config={v}
                  onChangeFuse={onChangeFuse}
                  onChangePutInWorkerName={onChangePutInWorkerName}
                />
              </div>
            ),
          })),
        ]}
      />
    </div>
  );
};

const RightOutput = ({
  workerName,
  onMenuClick,
}: {
  workerName?: string;
  onMenuClick: (workerName: string) => void;
}) => {
  const { enabledOutputSourceConfigs, reloadOutputSourceConfigs } =
    useModel('outputSource');
  const { enabledInputSourceConfigs } = useModel('inputSource');
  const { videoMatrixServer } = useModel('global');
  const [config, setConfig] = useState<InputSourceConfig>();

  useEffect(() => {
    for (let enabledInputSourceConfig of enabledInputSourceConfigs) {
      if (enabledInputSourceConfig.workerName === workerName) {
        setConfig(enabledInputSourceConfig);
        break;
      }
    }
  }, [enabledInputSourceConfigs, workerName]);

  useEffect(() => {
    reloadOutputSourceConfigs();
  }, []);

  return (
    <div className={styles.rightOutput}>
      <div className={styles.title}>输出源</div>
      <Menu
        selectedKeys={isNotBlank(workerName!) ? [workerName!] : undefined}
        onClick={(info) => {
          onMenuClick(info.key);
        }}
        style={{ width: 256 }}
        mode="inline"
        items={[
          ...enabledOutputSourceConfigs.map((v: InputSourceConfig) => ({
            key: v.workerName,
            label: v.label,
          })),
        ]}
      />
      <div className={styles.ptz}>
        {workerName?.includes('input') &&
          config?.pTZControl !== PTZControlType.None && (
            <>
              <div className={styles.title}>摄像头控制</div>
              <div className={styles.ptzControl}>
                <div className={styles.ptzUp}>
                  <SVG
                    className={styles.ptzSvg}
                    src="/img/ptz/angle-double-up.svg"
                    title="上移"
                    onMouseDown={() => {
                      move(videoMatrixServer, config!.workerName, { y: 0.5 });
                    }}
                    onMouseUp={() => {
                      stop(videoMatrixServer, config!.workerName);
                    }}
                  />
                </div>
                <div className={styles.ptzCenter}>
                  <SVG
                    className={styles.ptzSvg}
                    src="/img/ptz/angle-double-left.svg"
                    title="左移"
                    onMouseDown={() => {
                      move(videoMatrixServer, config!.workerName, { x: -0.5 });
                    }}
                    onMouseUp={() => {
                      stop(videoMatrixServer, config!.workerName);
                    }}
                  />
                  <SVG
                    className={styles.ptzSvg}
                    src="/img/ptz/reset.svg"
                    title="复位"
                    onClick={() => {
                      home(videoMatrixServer, config!.workerName);
                    }}
                  />
                  <SVG
                    className={styles.ptzSvg}
                    src="/img/ptz/angle-double-right.svg"
                    title="右移"
                    onMouseDown={() => {
                      move(videoMatrixServer, config!.workerName, { x: 0.5 });
                    }}
                    onMouseUp={() => {
                      stop(videoMatrixServer, config!.workerName);
                    }}
                  />
                </div>
                <div className={styles.ptzDown}>
                  <SVG
                    className={styles.ptzSvg}
                    src="/img/ptz/angle-double-down.svg"
                    title="下移"
                    onMouseDown={() => {
                      move(videoMatrixServer, config!.workerName, { y: -0.5 });
                    }}
                    onMouseUp={() => {
                      stop(videoMatrixServer, config!.workerName);
                    }}
                  />
                </div>
                <div className={styles.ptzZoom}>
                  <SVG
                    className={styles.ptzSvg}
                    src="/img/ptz/zoom-out.svg"
                    title="调焦 - "
                    onMouseDown={() => {
                      zoom(videoMatrixServer, config!.workerName, -0.5);
                    }}
                    onMouseUp={() => {
                      stop(videoMatrixServer, config!.workerName);
                    }}
                  />
                  <SVG
                    className={styles.ptzSvg}
                    src="/img/ptz/zoom-in.svg"
                    title="调焦 + "
                    onMouseDown={() => {
                      zoom(videoMatrixServer, config!.workerName, 0.5);
                    }}
                    onMouseUp={() => {
                      stop(videoMatrixServer, config!.workerName);
                    }}
                  />
                </div>
              </div>
            </>
          )}
      </div>
    </div>
  );
};

const CenterVideo = ({
  putInWorkerName,
  onChangePutInWorkerName,
  workerName,
  fuse,
}: {
  putInWorkerName?: string;
  workerName?: string;
  fuse: boolean;
  onChangePutInWorkerName: (putInWorkerName?: string) => void;
}) => {
  const [_message, contextHolder2] = message.useMessage();
  const { enabledOutputSourceConfigs, playback, updatePlayback } =
    useModel('outputSource');
  const { enabledInputSourceConfigs } = useModel('inputSource');
  const [config, setConfig] = useState<OutputSourceConfig>();
  const { recording, startRecord, stopRecord, recordingPath } =
    useModel('record');
  const { initialState } = useModel('@@initialState');
  const { videoMatrixServer, m7sServer, peerServer } = useModel('global');
  const { patient } = useModel('patient');
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    for (let enabledOutputSourceConfig of enabledOutputSourceConfigs) {
      if (enabledOutputSourceConfig.workerName === workerName) {
        setConfig(enabledOutputSourceConfig);
        break;
      }
    }
    for (let enabledInputSourceConfig of enabledInputSourceConfigs) {
      if (enabledInputSourceConfig.workerName === workerName) {
        setConfig(enabledInputSourceConfig);
        break;
      }
    }
  }, [enabledOutputSourceConfigs, enabledInputSourceConfigs, workerName]);

  const onDrop = (index: number, workerName: string = putInWorkerName!) => {
    playback(workerName, index, config as OutputSourceConfig);
    onChangePutInWorkerName(undefined);
  };

  useEffect(() => {
    const listener = () => {
      if (ref.current) {
        const height = ref.current.parentElement!.clientWidth * (9 / 16);
        if (height > ref.current.parentElement!.clientHeight) {
          const width = ref.current.parentElement!.clientHeight * (16 / 9);
          ref.current.style.width = width + 'px';
        } else {
          ref.current.style.height = height + 'px';
        }
      }
    };
    listener();
    window.addEventListener('resize', listener);
    return () => {
      window.removeEventListener('resize', listener);
    };
  }, []);

  return (
    <div className={styles.centerVideo}>
      {contextHolder2}
      <div className={styles.videoWrapper}>
        <div className={styles.video} ref={ref}>
          <LivePlayer
            type="SRS_WebRTC"
            controls={false}
            visible={true}
            cache={true}
            server={initialState!.videoMatrixIp!}
            streamKey="stream"
          />
          {fuse && (
            <div className={styles.fuseBarr}>
              {config?.splitScreenMode && (
                <div
                  className={[
                    styles.previewDrop,
                    // isNotBlank(putInSourceName!) ? styles.active : '',
                  ].join(' ')}
                >
                  {config.splitScreenMode === '1x1' && (
                    <div
                      className={styles._1x1}
                      onDragOver={(ev) => ev.preventDefault()}
                      onDrop={() => onDrop(0)}
                    >
                      <DropContainer
                        onDrop={({ workerName }) => onDrop(0, workerName)}
                      />
                    </div>
                  )}
                  {config.splitScreenMode === '1x2' && (
                    <>
                      <div
                        className={styles._1x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._1x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                    </>
                  )}
                  {config.splitScreenMode === '2x2' && (
                    <>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(2)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(2, workerName)}
                        />
                      </div>
                      <div
                        className={styles._2x2}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(3)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(3, workerName)}
                        />
                      </div>
                    </>
                  )}
                  {config.splitScreenMode === 'LEFT1xRIGHT3' && (
                    <>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(2)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(2, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT3}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(3)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(3, workerName)}
                        />
                      </div>
                    </>
                  )}
                  {config.splitScreenMode === 'LEFT1xRIGHT_BOTTOM1' && (
                    <>
                      <div
                        className={styles._LEFT1xRIGHT_BOTTOM1}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(0)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(0, workerName)}
                        />
                      </div>
                      <div
                        className={styles._LEFT1xRIGHT_BOTTOM1}
                        onDragOver={(ev) => ev.preventDefault()}
                        onDrop={() => onDrop(1)}
                      >
                        <DropContainer
                          onDrop={({ workerName }) => onDrop(1, workerName)}
                        />
                      </div>
                    </>
                  )}
                </div>
              )}
            </div>
          )}
        </div>
      </div>
      <div className={styles.toolBar}>
        <div className={styles.startRongPing}>
          <div
            title={recording ? '停止录制' : '开始录制'}
            className={[styles.toolIcon, recording ? styles.active1 : ''].join(
              ' ',
            )}
            onClick={() => {
              if (patient && patient.id) {
                if (recording) {
                  stopRecord(_message);
                } else {
                  startRecord(_message);
                }
              } else {
                _message.error('请选择一个患者');
              }
            }}
          >
            <SVG className={styles.toolIconSvg} src="/img/source/录制.svg" />
          </div>
          <div
            title="截图"
            className={styles.toolIcon}
            onClick={async () => {
              if (patient && patient.id) {
                const fileName = uuidV4();
                let dicPath: string;
                if (recordingPath) {
                  dicPath = recordingPath;
                } else {
                  dicPath = `${patient!.id}-${uuidV4()}`;
                  await setRecordPath(videoMatrixServer, dicPath);
                }
                const result = await saveScreenshot(
                  videoMatrixServer,
                  workerName!,
                  fileName + '.jpg',
                );

                if (result.success) {
                  let recordData: RecordDataType = {
                    fileType: 1,
                    fileName: dicPath,
                    fileUrl: `${
                      initialState!.miniIOServer
                    }/teach-manager-file/matrix/${dicPath}/${fileName}.jpg`,
                    uploadType: 0,
                    m7sRecordId: dicPath,
                    patientId: patient!.id,
                    recordType: 3,
                  };

                  const videoResult = await addVideo(peerServer, recordData);
                  if (videoResult.status === 200) {
                    _message.success('截图成功');
                  } else {
                    _message.success('截图上传失败');
                  }
                } else {
                  _message.error('截图失败');
                }
              } else {
                _message.error('请选择一个患者');
              }

              // console.log(result);
            }}
          >
            <SVG className={styles.toolIconSvg} src="/img/source/截图.svg" />
          </div>
        </div>
        {workerName?.includes('output') && (
          <div className={styles.splitScreen}>
            <div
              className={[
                styles.toolIcon,
                config?.splitScreenMode === '1x1' ? styles.active : '',
              ].join(' ')}
              onClick={() => {
                if (config) {
                  config.splitScreenMode = '1x1';
                  updatePlayback(config as OutputSourceConfig);
                }
              }}
            >
              <SplitScreen1 active={config?.splitScreenMode === '1x1'} />
            </div>
            <div
              className={[
                styles.toolIcon,
                config?.splitScreenMode === '1x2' ? styles.active : '',
              ].join(' ')}
              onClick={() => {
                if (config) {
                  config.splitScreenMode = '1x2';
                  updatePlayback(config as OutputSourceConfig);
                }
              }}
            >
              <SplitScreen2 active={config?.splitScreenMode === '1x2'} />
            </div>
            <div
              className={[
                styles.toolIcon,
                config?.splitScreenMode === '2x2' ? styles.active : '',
              ].join(' ')}
              onClick={() => {
                if (config) {
                  config.splitScreenMode = '2x2';
                  updatePlayback(config as OutputSourceConfig);
                }
              }}
            >
              <SplitScreen3 active={config?.splitScreenMode === '2x2'} />
            </div>
            <div
              className={[
                styles.toolIcon,
                config?.splitScreenMode === 'LEFT1xRIGHT3' ? styles.active : '',
              ].join(' ')}
              onClick={() => {
                if (config) {
                  config.splitScreenMode = 'LEFT1xRIGHT3';
                  updatePlayback(config as OutputSourceConfig);
                }
              }}
            >
              <SplitScreen4
                active={config?.splitScreenMode === 'LEFT1xRIGHT3'}
              />
            </div>
            <div
              className={[
                styles.toolIcon,
                config?.splitScreenMode === 'LEFT1xRIGHT_BOTTOM1'
                  ? styles.active
                  : '',
              ].join(' ')}
              onClick={() => {
                if (config) {
                  config.splitScreenMode = 'LEFT1xRIGHT_BOTTOM1';
                  updatePlayback(config as OutputSourceConfig);
                }
              }}
            >
              <SplitScreen5
                active={config?.splitScreenMode === 'LEFT1xRIGHT_BOTTOM1'}
              />
            </div>
          </div>
        )}
        {workerName?.includes('output') && (
          <div className={styles.stopRongPing}>
            <div
              title="清除融屏"
              className={styles.toolIcon}
              onClick={() => {
                if (config) {
                  config.splitScreenMode = '1x1';
                  config.previewConfig = [
                    undefined,
                    undefined,
                    undefined,
                    undefined,
                  ];
                  updatePlayback(config as OutputSourceConfig);
                }
              }}
            >
              <SVG
                className={styles.toolIconSvg}
                src="/img/split/清空资源.svg"
              />
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default () => {
  const [workerName, setWorkerName] = useState<string>();
  const [fuse, setFuse] = useState(false);
  const [putInWorkerName, setPutInWorkerName] = useState<string>();
  const { videoMatrixServer } = useModel('global');

  useEffect(() => {
    if (!fuse) {
      setPutInWorkerName(undefined);
    }
  }, [fuse]);

  useEffect(() => {
    getActive(videoMatrixServer).then((result) => {
      if (result.success) {
        setWorkerName(result.data);
      }
    });
  }, []);

  useEffect(() => {
    if (isNotBlank(workerName!)) {
      setActive(videoMatrixServer, workerName!);
    }
  }, [workerName]);

  return (
    <div className={styles.videoRouting}>
      <LeftInput
        putInWorkerName={putInWorkerName}
        workerName={workerName}
        onChangeFuse={setFuse}
        onChangePutInWorkerName={setPutInWorkerName}
        onMenuClick={setWorkerName}
      />
      <CenterVideo
        fuse={fuse}
        putInWorkerName={putInWorkerName}
        workerName={workerName}
        onChangePutInWorkerName={setPutInWorkerName}
      />
      <RightOutput workerName={workerName} onMenuClick={setWorkerName} />
    </div>
  );
};
